﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Baddies.Utils;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate;

namespace BaddiesEditor
{
    /// <summary>
    /// Keeps the data of the current project the user is working on.
    /// </summary>
    public class MapProject
    {
        /// <summary>
        /// Reference to the game.
        /// </summary>
        private EditorGame game;

        /// <summary>
        /// Reference to the form.
        /// </summary>
        private EditorForm form;

        /// <summary>
        /// File name ending for xml map files.
        /// </summary>
        private string mapEnding = ".map";

        /// <summary>
        /// File name ending for the xml project files.
        /// </summary>
        private string mapProjectEnding = ".mapproj";

        /// <summary>
        /// Name of the project.
        /// </summary>
        private string name;

        /// <summary>
        /// Tile size of the tileMap.
        /// </summary>
        private int tileSize;

        /// <summary>
        /// File url of the tilemap image.
        /// </summary>
        private string tileMapImageFileName;

        /// <summary>
        /// Name of the .map file asociated to this project.
        /// </summary>
        private string gameMapFileName;

        /// <summary>
        /// Initializes a new instance of the MapProject class.
        /// </summary>
        public MapProject()
        {
            this.game = null;
            this.form = null;
            this.Clear();
        }

        /// <summary>
        /// Sets the game reference.
        /// </summary>
        /// <value>Game reference.</value>
        public EditorGame Game
        {
            set { this.game = value; }
        }

        /// <summary>
        /// Sets the form reference.
        /// </summary>
        /// <value>Form reference.</value>
        public EditorForm Form
        {
            set { this.form = value; }
        }

        /// <summary>
        /// Gets or sets the name of the project.
        /// </summary>
        /// <value>Name of the project.</value>
        public string Name
        {
            get { return this.name; }
            set { this.name = value; }
        }

        /// <summary>
        /// Gets or sets the tile size.
        /// </summary>
        /// <value>Tile size of the map.</value>
        public int TileSize
        {
            get { return this.tileSize; }
            set { this.tileSize = value; }
        }

        /// <summary>
        /// Gets or sets the filename of the image used for the tile map.
        /// </summary>
        /// <value>Filename of the image of the tilemap.</value>
        public string TileMapImageFileName
        {
            get { return this.tileMapImageFileName; }
            set { this.tileMapImageFileName = value; }
        }

        /// <summary>
        /// Gets or sets the name of the map file.
        /// </summary>
        /// <value>Name of the map file.</value>
        public string GameMapFileName
        {
            get { return this.gameMapFileName; }
            set { this.gameMapFileName = value; }
        }

        /// <summary>
        /// Gets the end extension for the project file names.
        /// </summary>
        /// <value>The extension for the project file.</value>
        public string MapProjectEnding
        {
            get { return this.mapProjectEnding; }
        }

        /// <summary>
        /// Saves the project and the game in two different files.
        /// </summary>
        public void Save()
        {
            this.gameMapFileName = this.name + this.mapEnding;

            // Save XML with this class
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;

            using (XmlWriter writer = XmlWriter.Create(this.name + this.mapProjectEnding, settings))
            {
                IntermediateSerializer.Serialize(writer, this, null);
            }

            // Save another XML with the root node
            this.game.SaveMap(this.gameMapFileName);
        }

        /// <summary>
        /// Loads the project and game map.
        /// </summary>
        /// <param name="filename">File to load.</param>
        public void Load(string filename)
        {
            // Load this
            XmlReaderSettings settings = new XmlReaderSettings();

            using (XmlReader reader = XmlReader.Create(filename, settings))
            {
                MapProject serial = IntermediateSerializer.Deserialize<MapProject>(reader, null);

                this.name = serial.Name;
                this.tileSize = serial.tileSize;
                this.tileMapImageFileName = serial.tileMapImageFileName;
                this.gameMapFileName = serial.gameMapFileName;
            }

            // Load tileset image
            this.form.LoadTilesFromTileMap(this.tileMapImageFileName);

            // Load the root node XML
            this.game.LoadMap(this.gameMapFileName);
        }

        /// <summary>
        /// Clears the project to get it ready to load again.
        /// </summary>
        public void Clear()
        {
            this.name = string.Empty;
            this.tileSize = 0;
            this.tileMapImageFileName = string.Empty;
            this.gameMapFileName = string.Empty;
        }

        /// <summary>
        /// Gets whether the map project is initialized or not.
        /// </summary>
        /// <returns>True if it is, false otherwise.</returns>
        public bool Initialized()
        {
            return this.name != string.Empty;
        }
    }
}
